RemapCmd

Introduction

The RemapCmd module offers a way to reinterpret players' input that lies midway between a Doer and a StringPreParser. This module has been provided by Mitchell Mlinar; this documention page is closely based on his.

The RemapCmd class provides the following functionality:

Usage

The adv3Lite library header file (advlite.h) provides the following template for use with the RemapCmd class:

RemapCmd template 'cmd' @where? 'remappedCmd'?;

RemapCmd has one source text 'cmd' that contains one or more phrases (separated by ';') that supports grouping via '(...)' and or via '|'. Here is an example (and, yes, most of this would work natively but this is just an example).

Suppose we have a verb HoldUp (hold up) that takes one object. However, light and ceiling are not nouns and we don't want to define them but want to handle the paper. When you write your source text, it is very similar to a VerbRule:

RemapCmd 'hold paper up to light;hold paper against (|ceiling) light' @brightRoom 'hold up paper';

Here, the first item ('hold up...light') defines the cmd property, the second (@brightRoom) the where property (where the actor must be for this RemapCmd to be matched) and the third ('hold up paper') the remappedCmd property (the string the parser will interpret to execute the command).

With this definition of the cmd property the RemapCmd will consider any of the following player inputs a match:

If the player input matches one of these strings, the RemapCmd will replace that string with the command hold up paper — as if that is what the player typed in. However, it will ONLY do this if the player character's current location is brightRoom. (The where property can be defined as a Room, Region, or a list of Rooms and/or Regions.)

Another use case is to just emit some message(s) to the console. This is a great way to respond to some text without having to define all (or any) of the objects that entails writing some additional code to define words only used once. You do this by NOT specifying the remapped text and defining an execute() function on your RemapCmd object:


RemapCmd 'spit (|(on the ground))'
  execute()
  {
    "How often have you told yourself to quit doing that... ";
  }
;

So now when you run this, here is what you see:

>spit on the ground How often have you told yourself to quit doing that... >

Your may also use doInstead(...) within the execute method of a RemapCmd. It works much like using doInstead() in a Doer, for example:


RemapCmd 'sing loudly'
  execute()
  {
    doInstead(Yell);
  }
;

As in a Doer, do in a RemapCmd doInstead can take between one and four arguments: doInstead(action, dobj?, iobj?, aobj?). Also as in a Doer, you can use the macro goInstead() to bring about travel, e.g., goInstead(east). There are, however, a couple of things to note here. First, doInstead(...) (or goInstead()execute() method. Second, the turn counter will be affected by what the redirected doInstead(...) command does and the turnsTaken property defined on your RemapCmd onject will be ignored.

We don't have to use doInstead() at all; within reason, we can use the execute method of our RemapCmd to anything we like. To adapt an example from the original Colossal Cave Adventure, we could, for example, do something like this:


RemapCmd 'fee fie foe foo' @giantRoom
  execute()
  {
    eggs.moveInto(giantRoom);
    "The eggs you gave to the troll have mysteriously re-appeared on the floor in front of you. ";
  }
  when = eggs.isIn(troll)
;

RemapCmd defines the following properties/methods (of which the first three may be set via the template):

NOTE: RemapCmd has a restriction on the source text phrase in that, outside of the special characters described above, it does not allow any other special or punctuation characters other than comma ',' or apostrophe (').

Operation

RemapCmd parses up the cmd and does not make any attempt to map the words to existing objects in the game. Rather, it builds all the possible variations (by the use of "|", "(" and ")" operators) and then matches that against the user input FIRST before any other routines get a whack at it. You can also provide two or more disjoint phrases that are separated by semi-colon ";" to provide additional phrases that match.

Phrases can contain words enclosed in single quotes ('..') but you will need to use backslash as in \' within the text itself. This capability can be used to have a compound word with a space in it treated as one effective word.

RemapCmd takes advantage of string hashing to ensure high performance within your game.

RemapCmd modifies Parser.parse(str).

Finally, please note that RemapCmd takes effect before the parser has resolved the action and any objects involved in the command. That means that we cannot refer to gAction, gDobj or gIobj in any part of our RemapCmd definition, since these will be yet to be determined. In some cases this may make it difficult to define a cmd property that refers to the object we intend. For example if we have a crystal ball in one location and a football in other in our game and the player can refer to either object as simply 'ball' (which may seem quite unambigous to the player) a RemapCmd like the following may not always work as intended, especially :

RemapCmd 'play with (football| (foot|) ball))' 'throw football';

One can mitigate the risk here by adding a when condition, such as when = gPlayerChar.canReach(football), but in cases of potential ambiguity like this it may well be safer to use a Doer or SpecialVerb.